#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Purpose: Iras network exporter
# Created: 07/06/2009
# $Id $
# Copyright (c) 2008,2009 by University College London
# Authors:
#  --<>
#
# This program is free software under the GPL (>=v2)
# Read the file COPYING coming with HydroPlatform for details.

"""
This file is part of the OpenIRAS plugin for HydroPlatform.

It allows a user to export a network to a iras.inp file
"""
import codecs
import itertools
import logging
import numpy
import os
import wx


from sqlalchemy import and_, or_
from enthought.traits.api import HasTraits, Str, Enum, Int, Trait, Set

from hydroplatform.model.export import Exporter, ExportError, ExporterRegistry
from hydroplatform.model import network as nt
from hydroplatform.model import fields as fd

"""
POLICY_TYPE dict contains a key for the field
and the definition of the outputted policy
"""
POLICY_TYPE = {
    u"Flow input"        : (u"Gage", 1),
    u"Allocation"  : 2,
    u"Rate"        : 3,
    u"Power"       : 4,
    u"Pump"        : 5,
    u"Target Flow"      : (u"Target", 6),
    u"Target Storage"      : (u"Target", 6),
    u"Flow Target"      : (u"Target", 6),
    u"Refill Trigger (% fill in Lead Reservoir in group)"  : (u"Target",6),
    u"Source(s)"      : 7,
    u"Reservoir"        : (u"Rule", 8),
    u"Balance"     : 9,
    u"Evaporation Rate" : (u"Evaporation", 10),
    u"Evaporation Rate 1" : (u"Evaporation", 10),
    u"Evaporation Rate 2" : (u"Evaporation", 10),
    u"Evaporation/Rainfall Rate" : (u"Evaporation", 10),
    u"Loss Rate 1" : (u"Evaporation", 10),        
    u"Loss Rate 2" : (u"Evaporation", 10),    
    u"Loss Rate 3" : (u"Evaporation", 10),        
    u"Routing" :1,
    u"Transfer" : 2
}

NODE_POLICY_COMP = "node_component"
LINK_POLICY_COMP = "link_component"
COMPONENTS = {NODE_POLICY_COMP: 1,
              LINK_POLICY_COMP: 2}
# You are the
One = 1
class Policy(HasTraits):
    """
    Class that represents an IRAS policy for a given nodetype
    (even if IRAS supports it a the node level)
    
    !PolicyGrpID,PolicyType,PolicyID,CompType,CompID (iNodeLinkID),
    BegDate,EndDate
    !CompType says if its a for a node (CompType=1) or link (2)
    """
    policy_group_id = Int
    policy_type = Trait("Gage", POLICY_TYPE)
    policy_id = Int
    comp_type = Trait(NODE_POLICY_COMP, COMPONENTS)
    beg_date = Int
    end_date = Int    
    valid_ids = Set(Int, label="list of id's that use this policy")
    
    
    def __str__(self):
        return "%s %s %s %s %s %s" % (self.policy_group_id,
                                      self.policy_type,
                                      self.policy_id,
                                      self.comp_type,
                                      self.beg_date,
                                      self.end_date)
    
    def export_str_policy(self, obj, session):
        """
        Export this policy to text for the given oid
        """
        # this is to avoid exporting policies with no values
        # Presumes that there is a value
        for i in obj.type.fields:
          if self.policy_type==i.name:
            val = obj.getFieldValue(session,i)
            if val ==None:
              return None
            if val.value==None:
              return None
          else:
            continue

          return "%s: %i,%i,%i,%i,%i,%s,%.3f !%s\n" % \
                 (self.policy_type_[0],
                  self.policy_group_id,
                  self.policy_type_[1],
                  self.policy_id,
                  self.comp_type_,
                  obj.id,
                  self.beg_date,
                  self.end_date - 0.001,
                  obj.name
                  )

class IrasExporter(Exporter):
    '''
    Exports network to a iras.inp file to be run with OpenIRAS
    '''
    _name = "IRAS exporter"
    _description  = '''Exports a network to an iras.inp file '''
    
    def __init__(self):
        Exporter.__init__(self)
        self.session = None
        self.fields = dict()
    
    def export(self, network, path, session=None, days_per_period=365, \
               sub_time_steps=10, total_runs=1, default_evap_rate=2, user_node_seq=0):
        '''
        Export an Excel workbook to the given filename
        '''
        if session is None:
            raise ExportError(u"Cannot export without a session object")
        self.session = session
        assert isinstance(network, nt.Network)
        
        if os.path.isdir(path):
            basedir = path
        else:
            basedir = os.path.dirname(path)
        
        self.compute_policies(network, session)
        
        inpfile = os.path.join(basedir, "iras.inp")
        ofile = codecs.open(inpfile, mode="w", encoding="utf-8")
        self.write_nodes(network, ofile, session)
        self.write_links(network, ofile, session)
        self.write_evaporation(network, ofile, session)
        self.write_rating_tables(network, ofile, session)
        self.write_allocation_function(network, ofile, session)
        self.write_targets(network, ofile, session)
        self.write_sources(network, ofile, session)
        self.write_dem_red(network, ofile, session)
        self.write_performance(network, ofile, session)
        self.write_link_cost(network, ofile, session)
        self.write_reservoir_groups(network, ofile, session)
        self.write_pump_hydropower(network, ofile, session)
        self.write_groundwater(network, ofile, session)
        self.write_routing(network, ofile, session)
        ofile.write('SysEvaporation: 1 %s' % default_evap_rate)
        ofile.close()
        
        gagefile = os.path.join(basedir, "iras.gag")
        flowfile = os.path.join(basedir, "iras.flw")
        demfile = os.path.join(basedir, "iras.dem")
        ofile = codecs.open(gagefile, mode="w", encoding="utf-8")
        ffile = codecs.open(flowfile, mode="w", encoding="utf-8")
        #Evgenii added demfile 4/4/11
        dfile = codecs.open(demfile, mode="w", encoding="utf-8")
        self.write_gage(network, ofile, ffile, dfile, session)
        ofile.close()
        ffile.close()
        dfile.close()
        
        deffile = os.path.join(basedir, "iras.def")
        ofile = codecs.open(deffile, mode="w", encoding="utf-8")
        # FIXME : hardcoded parameters in export
        self.write_def(network, ofile, session, sub_time_steps, \
                       days_per_period, user_node_seq, total_runs)
        ofile.close()
        
        polfile = os.path.join(basedir, "iras.pol")
        ofile = codecs.open(polfile, mode="w", encoding="utf-8")
        self.write_pol(network, ofile, session)
        ofile.close()
        
        untfile = os.path.join(basedir, "iras.unt")
        ofile = codecs.open(untfile, mode="w", encoding="utf-8")
        self.write_unt(network, ofile, session)
        ofile.close()

        chgfile = os.path.join(basedir, "iras.chg")
        ofile = codecs.open(chgfile, mode="w", encoding="utf-8")
        self.write_chg(network, ofile, session)
        ofile.close()        
         # Create a message dialog box
        class MessageDialog(wx.Frame):
          def __init__(self, parent, id, title):
            wx.Frame.__init__(self, parent, id, title)

            wx.FutureCall(1, self.ShowMessage)

       
          def ShowMessage(self):
            wx.MessageBox('Export Completed', 'Info')


        app = wx.App()
        MessageDialog(None, -1, 'MessageDialog')
        app.MainLoop()
 
        #FIXME: ADD WX WINDOW.
    def compute_policies(self, network, session):
        """
        Compute the dictionnary of policies that are defined on the system
        
        Returns a dictionnary of policies using the node.type as key and a list
        of policies as values
        """
        self.policies = dict()
        self.policies_fields = dict()
         #for each objecttype check the policies        
        for node in network.nodes:
            if not self.policies.has_key(node.type):
                self.policies[node.type] = list()
                self.generate_policies_for_otype(node, node.type)
            else:
                continue
        for link in network.links:
            if not self.policies.has_key(link.type):
                self.policies[link.type] = list()
                self.generate_policies_for_otype(node, link.type)
            else:
                continue
                                    
    
    def generate_policies_for_otype(self, nn, otype):
        """
        Generate the list of Policy object for the given object type
        """
        com_type = NODE_POLICY_COMP if isinstance(otype, nt.NodeType) \
                 else LINK_POLICY_COMP
               
        #if otype.name not in POLICY_TYPE.keys():
        #    # do not parse object types that are not linked to any policies
        #    logging.info("No policy defined for %s" % otype.name)
        #    return
            
        # for each time dependant field
        for field in otype.fields:  
            #if self.has_value(nn, field.name) == 1:
            #Evgenii - I had added this line to make sure policies only exported for those seasonal paramters that have data
            #           but this doesn't work for networks with multple nodes of the same node type (or links) where in one you have
            #           the data in the seasonal field and in the other not.
                #logging.info("Field %s is not seasonal" % field)
            pols = self.generate_policies_for_field(field, com_type)
            self.policies[otype].extend(pols)
            self.policies_fields[field] = pols
        if isinstance(otype, nt.NodeType) and otype.name == u"Reservoir":
            #add a custom policy for reservoir
            self.reservoir_pol = Policy(policy_group_id=1,
                policy_type=otype.name,
                policy_id=1,
                comp_type=NODE_POLICY_COMP,
                beg_date=1,
                end_date=365)
            self.policies[otype].append(self.reservoir_pol)
        
    def generate_policies_for_field(self, field, com_type):
        """
        Returns the list of policies for the given field
        
        
        Using end day of the year = 366, as we do export it as 366-0.1
        """
        att = field.attribute_type
        pols = list() 
        if isinstance(att, fd.SeasonalParameter):
            
            # check the policy does not already exists
            if self.policies_fields.has_key(att):
                #existing policy
                return self.policies_fields[att]
            
            # there can be more than one policy for this field
            # there is one policy for this field
            grp_count = itertools.count(1)
            type_count = itertools.count(1)
            group_id = grp_count.next()
            dates = att._dates
            if att.horizon is True:
                # FIXME : improve the leap year computation
                import calendar
                import datetime
                from dateutil.relativedelta import relativedelta
                if calendar.isleap(att._dates[0].year):
                    r = relativedelta(years=1)
                    logging.warn("Leap year in policy : skipped to the next year")
                    # go to the next year
                    dates = [d+r for d in att._dates]
                    print dates
            
            for i in xrange(len(dates)):
                d1 = dates[i]
                if i == len(dates)-1:
                    # if horizon is yearly, the last day MUST be 365
                    #if att.horizon is True:
                    d2 = d1
                    end_date = 366
                else:
                    d2 = dates[i+1]
                    end_date = int(d2.strftime("%j"))
                    
                    
                beg_date = int(d1.strftime("%j"))
                    
                if d2.year == d1.year:
                    pols.append(
                        Policy(policy_group_id=group_id,
                           policy_type=field.name,
                           policy_id=type_count.next(),
                           comp_type=com_type,
                           beg_date=beg_date,
                           end_date=end_date))
                else:
                    # write a group until end of the year    
                    pols.append(\
                        Policy(policy_group_id=group_id,
                               policy_type=field.name,
                               policy_id=type_count.next(),
                               comp_type=com_type,
                               beg_date=beg_date,
                               end_date=366))
                    # increase group id
                    group_id = grp_count.next()
                    # restart the type count at 1
                    type_count = itertools.count(1)
                    if d2.day != 1 :
                        pols.append(\
                            Policy(policy_group_id=group_id,
                                   policy_type=field.name,
                                   policy_id=type_count.next(),
                                   comp_type=com_type,
                                   end_date=end_date,
                                   beg_date=1))    
        else:
            logging.info("Field %s is not seasonal" % field.name)
            # generate a policy for the all period
                        
        self.policies_fields.setdefault(att, pols)
        
        return pols
        
    def write_nodes(self, network, ofile, session):
        """
NODES
1  0 0 0  0 400 300 1 0 4 1 0 0 0 0 0 0  0 Res1
END OF NODES

        """
        # write the nodes
        ofile.write("NODES\n")
        nodes = []
        # store nodes
        for node in network.nodes:
            nodes.append(
                        (node.id,
                         self.get_value(node, u"Elevation"),
                         self.get_value(node, u"Storage Capacity"),
                         self.get_value(node, u"Initial Storage"),
                         self.has_value(node, u"Flow Input"),   
                         self.get_value(node, u"Rule Group ID"),
                         (node.type.name == u"Reservoir") and 1 or 0,
                         (node.type.name == u"Lake") and 1 or 0,
                         (node.type.name in [u"Aquifer", u"Wetland"]) and 1 or 0,
                         self.is_dey_demand(node),
                         self.node_has_link_with(node, session,
                                                 u"Hydropower Enabled?"),
                         self.node_has_link_with(node, session,
                                                 u"Pumping Enabled?"),
                         node.name[:25]
                         )
                        )
        self.output_formatted_lines(nodes, ofile)
                                     
        ofile.write("END OF NODES\n")
        
    def is_dey_demand(self, node):
        """
        Return 1 if node has the following properties :
        - it is a Demand or Demand/Consumption node
        - Target Storage has a value if node is a Lake or Reserver
        """
        if node.type.name in [u"Demand", u"Demand/Consumption"]:
            return 1
        elif node.type.name in [u"Reservoir", u"Lake"] and \
            not numpy.alltrue(numpy.isnan(self.get_value(node, u"Target Storage"))) :
            return 1
        else: return 0
        
    def node_has_link_with(self, node, session,
                           binary_field=u"Hydropower Enabled?"):
        """
        Return the link id of the link that would have this node as upstream
        node and link has the binary_field field switched on
        
        FIXME : what if the link id is 0 ...
        """
        links = session.query(nt.Link).filter(nt.Link.start_node_id == node.id).all()
        if len(links) > 0:
            for link in links:
                if self.get_value(link, binary_field, False) > 0:
                    return link.id                
        return 0
        
    def write_links(self, network, ofile, session):
        """
LINKS
1  1  2  0   0   0 1 0 0 0 0 0 Res1-Jct
END OF LINKS
        """
       # write the nodes
        ofile.write("LINKS\n")
        links = []
        # store nodes
        for link in network.links:
            links.append( (link.id,
                           link.start.id,
                           link.end.id,
                           self.get_depending_value(link, u"Loss Method", u"Length"),
                           self.get_value(link, u"Time-Step Flow Capacity"),
                           self.get_value(link, u"Annual Flow Capacity"),
                           self.get_depending_value(link, u"Routing Method", u"Initial Storage"),
                           (link.type.name.find(u"Diversion") > -1) and 1 or 0,
                           link.type.name.startswith(u"Demand") and 1 or 0,
                           (link.type.name in [u"Groundwater Link",
                                               u"Surface Bidirectional Link"]) and 1 or 0,
                           link.name[:25]
                           )
                          )
        self.output_formatted_lines(links, ofile)
            
        ofile.write("END OF LINKS\n")
    
        
    def write_link_cost(self, network, ofile, session):
        """
        Prints costs for all type of links except Default Link.
        
        A cost line is printed only if one of the following parameters
        has a value: 'Price per kWh', 'kWh per m3', 'Annual Energy Cost Increase'.
        """
        ltypes = self.session.query(nt.LinkType).filter( \
                or_(nt.LinkType.name == u"Diversion/Demand Link",
                    nt.LinkType.name == u"Unidirectional Link",
                    nt.LinkType.name == u"Demand Link",
                    nt.LinkType.name == u"Diversion Link",
                    nt.LinkType.name == u"Groundwater Link",
                    nt.LinkType.name == u"Surface Bidirectional Link",
                    nt.LinkType.name == u"Demand/Diversion Link")).all()
        link_costs = []
        for link in network.links:
            if link.type in ltypes:
                price_per_kwh = self.get_value(link, u"Price per kWh", False)
                power = self.get_value(link, u"kWh per m3", False)
                annual_energy_cost = self.get_value(link, u"Annual Energy Cost Increase", False)
                if price_per_kwh > 0 or power > 0 or annual_energy_cost > 0:
                    link_costs.append((u"Cost:", 1, 1, link.id,
                                       price_per_kwh,
                                       power,
                                       annual_energy_cost))
        if link_costs.__len__() > 0:
            self.output_formatted_lines(link_costs, ofile)
    
    
    def write_evaporation(self, network, ofile, session):
        """
        Evaporation for nodes and links.
        
        Only for Default and Diversion links
        """
        ofile.write(
"""
**************LOSS FOR NODES********************
""")
        ntypes = self.session.query(nt.NodeType).filter( \
                or_(nt.NodeType.name == u"Lake",
                    nt.NodeType.name == u"Wetland",
                    nt.NodeType.name == u"Reservoir")).all()
        for node in network.nodes:
            if node.type in ntypes:
                # manage policies for evaporation in iras.pol
                self.policies[node.type]
                fname = u"Evaporation/Rainfall Rate"
                val = self.get_value(node, fname, False)
                if self.has_value(node, fname) is 1:
                    if val is None:
                        continue    
                    elif isinstance(val, numpy.ndarray):
                        if numpy.alltrue(numpy.isnan(val)):
                            continue
                    
                    #logging.warning("node is %s, val is %s" %node.id %val)
                    pols = self.generate_policies_for_field( \
                                    self.get_objectfield(node.type, fname), \
                                    NODE_POLICY_COMP)
                    logging.debug("Exporting evaporation for node %s" % node.id)                
                    One = '1'
                    # The number one is exported to for the year column (pol group id)
                    # because annual changes not implemented in IRAS
                    for i, pol in enumerate(pols):
                        try:
                            try:
                                evaporation = val[i,0]
                            except TypeError:
                                evaporation = val
                            if abs(evaporation - 0.0) > 1e-10 :
                                ofile.write("%s: %s %s %s %s %s \n" % \
                         # MARK
                         # There seems to be come kind of problem here,
                         # according to Matrosoe, something to do with midyear
                         # beg_dates. Must follow this up with him, still unclear.
                                (pol.policy_type_[0],
                                    One,
                                    pol.policy_id,
                                    pol.comp_type_,
                                    node.id,
                                    evaporation))
                            pol.valid_ids.add(node.id)
                        except IndexError:
                            logging.warning("Missing value for evaporation in file")
                    else:
                        logging.debug('No value %s for %s' % (fname, node.id))        
        ofile.write(
"""
**************LOSS FOR LINKS********************
"""
        )
                    
        ltypes = self.session.query(nt.LinkType).filter( \
                or_(nt.LinkType.name == u"Diversion/Demand Link",
                    nt.LinkType.name == u"Unidirectional Link",
                    nt.LinkType.name == u"Demand Link",
                    nt.LinkType.name == u"Diversion Link")).all()
        ratings = []
        crossections = []
        for link in network.links:
            if link.type in ltypes:
                # manages policies for evaporation in iras.pol
                policy = self.policies[link.type]
                cm = int(self.get_value(link, u"Loss Method", \
                                    False))
                if cm > 0:
                    if cm > 1:
                        # There is a Loss Rate SP only for value 2 and 3
                        fname = u"Loss Rate %s" % int(cm )
                        if self.has_value(link, fname):
                            val = self.get_value(link, fname, False)
                            pols = self.generate_policies_for_field( \
                                    self.get_objectfield(link.type, fname), \
                                    LINK_POLICY_COMP)
                            logging.debug("Exporting evaporation for link %s" % link.id)
                            if link.id == 129:
                                print link.id, val
                            for i, pol in enumerate(pols):
                                try:
                                    evaporation = val[i,0]
                                except IndexError:
                                    logging.warning("Missing value for evaporation in file")
                                    evaporation = "0"
                                ofile.write("%s: %s %s %s %s %s %s \n" % \
                                      (pol.policy_type_[0],
                                        One,
                                        pol.policy_id,
                                        pol.comp_type_,
                                        link.id,
                                        evaporation,
                                        int(cm) - 1 ))
                                pol.valid_ids.add(link.id)
                                logging.debug("Added %s - %s" % (pol, link.id))
                        else:
                            logging.debug('No value %s for %s' % (fname, link.id))
                    if cm == 1:
                        ofile.write("%s: %s %s %s %s %s %s \n" % \
                                      (u"Evaporation",
                                       1,
                                       1,
                                       2,
                                       link.id,
                                        0,
                                        0))
                    cm = int(cm) -1
                    if cm == 0:
                        # get the ratings table
                        fname = u"Loss Table"
                        if self.has_value(link, fname ):
                            rate_table = self.get_value(link, fname, False)
                            for rowid in xrange(rate_table.shape[0]):
                                ratings.append(("Rating:", 1, 1,
                                                COMPONENTS[LINK_POLICY_COMP],
                                                link.id, 0,
                                                rate_table[rowid, 1],
                                                rate_table[rowid, 0]))
                    elif cm == 1:
                        # get the ratings table
                        fname = u"Width Table"
                        if self.has_value(link, fname ):
                            rate_table = self.get_value(link, fname, False)
                            for rowid in xrange(rate_table.shape[0]):
                                ratings.append(("Rating:", 1, 1,
                                                COMPONENTS[LINK_POLICY_COMP],
                                                link.id,
                                                rate_table[rowid, 1],
                                                0,
                                                rate_table[rowid, 0]))
                    elif cm == 2:
                        # get the crossection  values
                        crossections.append(('CrossSection:', 1, 1,
                                             COMPONENTS[LINK_POLICY_COMP],
                                             link.id,
                                             self.get_value(link, u"Base Width"),
                                             self.get_value(link, u"Channel Depth"),
                                             self.get_value(link, u"Lower Left Slope"),
                                             self.get_value(link, u"Lower Right Slope"),
                                             self.get_value(link, u"Upper Left Slope"),
                                             self.get_value(link, u"Upper Right Slope"))
                                            )
                    else:
                        logging.debug("CM value not set for link %s" % link.name)
                else:
                    logging.debug("No evaporation value for link %s " \
                                % link.name)
                        
        if len(ratings) > 0:
            ofile.write("---Rating tables for links--------\n")
            self.output_formatted_lines(ratings, ofile)
        if len(crossections) > 0:
            ofile.write("--------CROSS SECTION\n")
            self.output_formatted_lines(crossections, ofile)
                        
    def write_rating_tables(self, network, ofile, session):
        """
        Write rating tables to iras.inp files
        """
        ofile.write(
"""
**************Rating tables********************
------Nodes------
"""
        )
        # process nodes
        ntype = self.session.query(nt.NodeType).filter( \
                or_(nt.NodeType.name == u"Lake",
                    nt.NodeType.name == u"Wetland",
                    nt.NodeType.name == u"Aquifer",
                    nt.NodeType.name == u"Reservoir")).all()
        
        ratings = []
        for node in network.nodes:
            # get rating table
            fname = u"Rating Table"
            if self.has_value(node, fname):
                rate_table = self.get_value(node, fname, False)
                for rowid in xrange(rate_table.shape[0]):
                    if node.type.name == u"Reservoir":
                        if rate_table.shape[1] > 5:
                            max_release = rate_table[rowid, 4]
                            discharge = rate_table[rowid, 5]
                        else:
                            max_release = 0
                            discharge = 0
                    elif node.type.name == u"Lake":
                        max_release = 0                        
                        if rate_table.shape[1] > 4:
                            discharge = rate_table[rowid, 4]
                        else:
                            discharge = 0
                    else:
                        max_release = 0
                        discharge = 0
                    ratings.append(
                            ("Rating:",
                             1,
                             1,
                             COMPONENTS[NODE_POLICY_COMP],
                             node.id,
                             rate_table[rowid,0], # elevation
                             rate_table[rowid,1], # Area
                             rate_table[rowid,2], # Volume
                             rate_table[rowid,3], # Seeprate
                             max_release,
                             discharge
                             ))
        self.output_formatted_lines(ratings, ofile)
        ofile.write("------Links------\n")
        ltypes = self.session.query(nt.LinkType).filter( \
                or_(nt.LinkType.name == u"Default link",
                    nt.LinkType.name == u"Diversion")).all()
        for link in network.links:
            if link.type in ltypes:
                # manages policies for evaporation in iras.pol
                policy = self.policies[link.type]
                cm = self.get_value(link, u"Evaporation Computation Method", \
                                    False)
                if cm is 0:
                    fname = u"Rating Table 0"
                    if self.has_value(link, fname ):
                        rate_table = self.get_value(link, fname, False)
                        for rowid in xrange(rate_table.shape[0]):
                            ofile.write("Rating: 1 1 %s %i 0 0 0 0 0 %s 0 0 %s 0\n" %
                                    (COMPONENTS[LINK_POLICY_COMP],
                                     link.id,
                                     rate_table[rowid,0], # Loss Flow
                                     rate_table[rowid,1], # Flow
                                     ))
                if cm is 1:
                    fname = u"Rating Table 1"
                    if self.has_value(link, fname ):
                        rate_table = self.get_value(link, fname, False)
                        for rowid in xrange(rate_table.shape[0]):
                            ofile.write("Rating: 1 1 %s %i 0 0 %s 0 0 0 0 0 %s 0\n" %
                                    (COMPONENTS[LINK_POLICY_COMP],
                                     link.id,
                                     rate_table[rowid,0], # Width
                                     rate_table[rowid,1], # Flow
                                     ))
    
    def write_allocation_function(self, network, ofile, session):
        """
        FIXME : add alignemnt to the output
        """
        ofile.write(
"""
*****Allocation and Consumption Functions*****
** Allocation function
"""
        )
        
        # for nodes being upstream of a diversion link, output the allocation
        # table
        ltypes = self.session.query(nt.LinkType).filter( \
                or_(nt.LinkType.name == u"Diversion Link",
                    nt.LinkType.name == u"Demand/Diversion Link")).all()
        ratings = []
        for link in network.links:
            if link.type in ltypes:
                fname = u"Allocation Function"
                if self.has_value(link, fname):
                    rating_table = self.get_value(link, fname, False)
                    for rowid in xrange(rating_table.shape[0]):
                        ratings.append(("Allocation:",
                                        1,
                                        1,
                                        COMPONENTS[NODE_POLICY_COMP],
                                        link.start.id,
                                        rating_table[rowid,0], # Total flow
                                        link.id,
                                        rating_table[rowid,1], # Total allocated
                                 ))
        self.output_formatted_lines(ratings, ofile)
        
        ofile.write("**Consumption functions\n")
        ntypes = self.session.query(nt.NodeType).filter(\
            and_(or_(nt.NodeType.name == u"Consumption",
                nt.NodeType.name == u"Demand/Consumption"),
            nt.NodeType.project_id == network.project_id)).all()
        for node in network.nodes :
            if node.type in ntypes:
                logging.debug("Consumption function for %s - %s" % \
                              (node, node.type))
                fname = u"Consumption Function"
                if self.has_value(node, fname) is 1:
                    rating_table = self.get_value(node, fname, False)
                    for rowid in xrange(rating_table.shape[0]):
                        ofile.write("Allocation: 1 1 %s %i %s 0 %s\n" %
                                (COMPONENTS[NODE_POLICY_COMP],
                                 node.id,
                                 rating_table[rowid,0],
                                 rating_table[rowid,1],
                                 ))       
                else:
                    logging.debug("No consumption table for %s" % node)
        ofile.write("END OF ALLOCATION")
 
    def write_targets(self, network, ofile, session):
        """
        Write the target and sources tables
        """
        ofile.write(
"""            
*******Targets and Sources**********
"""
        )
        ntypes = self.session.query(nt.NodeType).filter(\
            and_(or_(nt.NodeType.name == u"Demand",
                nt.NodeType.name == u"Demand/Consumption",
                nt.NodeType.name == u"Reservoir",
                nt.NodeType.name == u"Lake"),
            nt.NodeType.project_id == network.project_id)).all()
        targets = list()        
        for node in network.nodes :
            if node.type in ntypes:
                if node.type.name in [u"Demand", u"Demand/Consumption"]:
                    fname = u"Target Flow" #Evgenii - why is this here?
                    if self.get_value(node, u"Do not consider passive water?") > 0:
                        passive_water = 1
                    else:
                        passive_water = 0
                    demand_growth = self.get_value(node, u"Annual Demand Growth", False)                    
                else:
                    fname = u"Target Storage" #Evgenii- Why is this inside the if(demand or demand/consumption)
                    passive_water = 0
                    demand_growth = 0.0
                    
                if self.has_value(node, fname) is 1 and node.type.name == u"Reservoir":
                    refill_trigger =  self.get_value(node, u"Refill Trigger (% fill in Lead Reservoir in group)", False)
                    
                    rtrigger="0.0"
                    target_flow = self.get_value(node, fname, False)
                    carry_over = self.get_value(node, u"Carry Over")
                    pols = self.generate_policies_for_field( \
                            self.get_objectfield(node.type, fname), \
                                NODE_POLICY_COMP)
                    priorities=self.get_value(node, u"Enable source priorities?")
                    logging.debug("Exporting target flow for %s" % node.id)
                    for i, pol in enumerate(pols):
                        print i, pol
                        try:
                            tflow = target_flow[i,0]
                        except IndexError:
                            logging.warning("Missing value for target flow for %s" % node)
                            tflow = "0"
                        try:
                            rtrigger = refill_trigger
                        except IndexError:
                            logging.warning("Missing value for target flow for %s" % node)
                            rtrigger = "0"
                        targets.append(
                                      ("Target:",
                                        One,
                                        pol.policy_id,
                                        pol.comp_type_,
                                        node.id,
                                        tflow,     # target flow value
                                        carry_over, # carry_over is a node Parameter
                                        passive_water,
                                        rtrigger,
                                        demand_growth,
                                        priorities
                                        ))
                elif self.has_value(node, fname) is 1: #evgenii - ??
                    target_flow = self.get_value(node, fname, False)               
                    carry_over = self.get_value(node, u"Carry Over")
                    priorities=self.get_value(node, u"Enable source priorities?")
                    #add priorities here
                    pols = self.generate_policies_for_field( \
                            self.get_objectfield(node.type, fname), \
                                NODE_POLICY_COMP)
                    logging.debug("Exporting target flow for %s" % node.id)
                    for i, pol in enumerate(pols):
                        print i, pol
                        try:
                            tflow = target_flow[i,0]
                        except IndexError:
                            logging.warning("Missing value for target flow for %s" % node)
                            tflow = "0"
                        
                        targets.append(
                                      ("Target:",
                                        One,
                                        pol.policy_id,
                                        pol.comp_type_,
                                        node.id,
                                        tflow,     # target flow value
                                        carry_over, # carry_over is a node Parameter
                                        passive_water,
                                        "0",
                                        demand_growth,
                                        priorities
                                        ))
                else:
                    # logging.debug("No target flow table for %s" % node)
                # fname = u"Source(s)"        
                # if self.has_value(node, fname) is 1:
                    # source_table = self.get_value(node, fname, False)
                    # for row in source_table:
                        # targets.append(("Source:",
                                        # 1,
                                        # 1,
                                        # COMPONENTS[NODE_POLICY_COMP],
                                        # node.id,
                                        # int(row[0]),
                                        # int(row[1]),  
                                        # row[2]
                                        # ))
                    logging.debug("No source node value for %s" % node)      
        if len(targets) > 0:
            self.output_formatted_lines(targets, ofile)
    #Evgenii 070411 separated Target and Sources
    def write_sources(self, network, ofile, session):
        """
        Write the sources
        """
        ntypes = self.session.query(nt.NodeType).filter(\
            and_(or_(nt.NodeType.name == u"Demand",
                nt.NodeType.name == u"Demand/Consumption",
                nt.NodeType.name == u"Reservoir",
                nt.NodeType.name == u"Lake"),
            nt.NodeType.project_id == network.project_id)).all()
        sources = list()        
        for node in network.nodes :
            if node.type in ntypes:
                fname = u"Source(s)"        
                if self.has_value(node, fname) is 1:
                    source_table = self.get_value(node, fname, False)
                    for row in source_table:
                        sources.append(("Source:",
                                        1,
                                        1,
                                        COMPONENTS[NODE_POLICY_COMP],
                                        node.id,
                                        int(row[0]),
                                        int(row[1]),
                                        row[2],
                                        row[3],
                                        row[4],
                                        row[5]
                                        ))
                else:
                    logging.debug("No source node value for %s" % node)      
        if len(sources) > 0:
            #logging.debug("Going into sources export, length of sources is %s" % len(sources))  
            #f = open('output1.txt', 'w')
            #f.write("%s\n" % len(targets))
            #f.write("%s\n" % len(targets[0]))
            #for item in targets:
            #    f.write("%s\n" % targets)
            # f.write("%s\n" % targets[0])
            # f.write("%s\n" % len(targets[0]))
            #f.write("%s\n" % xrange(len(targets[0]))            
            #formats = [1 for i in xrange(len(targets[0]))]
            #f.close()
            self.output_formatted_lines(sources, ofile)

    def write_dem_red(self, network, ofile, session):
        ofile.write(
"""            
*******DemRed**********
"""
        )
        ntypes = self.session.query(nt.NodeType).filter(\
            and_(or_(nt.NodeType.name == u"Demand",
                nt.NodeType.name == u"Demand/Consumption",
                nt.NodeType.project_id == network.project_id))).all()
        demred = list()
        for node in network.nodes :
            if node.type in ntypes:
                linked_node = self.get_value(node, u"Linked Storage Node", False)
                table = self.get_value(node, u"Demand Reduction Table", False)
                if numpy.alltrue(table == 0):
                    continue
                for row in table:
                    output = [u"DemRed:", 1, 1,"%i" % node.id,"%i" % linked_node]
                    for val in row:
                        output.append(val)
                    demred.append(output)
        if len(demred) > 0:
            self.output_formatted_lines(demred, ofile)
            
    def write_performance(self, network, ofile, session):
        ofile.write(
"""            
*******Performance**********
"""
        )
        ntypes = self.session.query(nt.NodeType).filter(\
            and_(or_(nt.NodeType.name == u"Demand",
                nt.NodeType.name == u"Demand/Consumption",
                nt.NodeType.name == u"Reservoir",
                nt.NodeType.name == u"Wetland",
                nt.NodeType.name == u"Aquifer",
                nt.NodeType.project_id == network.project_id))).all()
        performance = list()
        for node in network.nodes :
            if node.type in ntypes:
                table = self.get_value(node, u"Performance Thresholds", False)                
                if table is 0: #numpy.alltrue(table == 0):
                    continue
                if table[0,0] or table[0,0] == '-1.#IND':
                    continue
                for row in table:
                    for row in table:
                        output = [u"Performance:", 1, 1,"%i" % node.id]
                        output.append(val)
                    performance.append(output)
        if len(performance) > 0:
            self.output_formatted_lines(performance, ofile)                
                    
    def write_reservoir_groups(self, network, ofile, session):
        """
        Write the reservoir info to the output file
        """
        ofile.write("************* Reservoir Groups***************\n")
        ntype = self.session.query(nt.NodeType).filter(\
               and_(nt.NodeType.name == u"Reservoir",
                    nt.NodeType.project_id == network.project_id)).first()
        rules = list()
         #Evgenii 3-31-11 made gid=0 to prevent error in case gid is not defined in DB         
        gid=0
        for node in network.nodes :
            if node.type == ntype:      
                gid  = self.get_value(node, u"Rule Group ID", False)
                #Evgenii 3-31-11 added if below in case Res does not have group id
                if not bool(gid):
                        print "Error - Reservior needs Group ID"
                        continue
                print "Rule group ID is %s for node id %s" % (gid, node.id)
                if node.id in gid:
                    table = self.get_value(node, u"Rule Table", False)
                    if table is 0:
                        continue
                    print "Exporting rule for node %s" % node.id
                    for row in table:
                        output = [u"Rule:", 1, 1, "%i" % node.id]
                        for val in row:
                            output.append(val)
                        rules.append(output)
                    self.reservoir_pol.valid_ids.add(node.id)
                        
        if len(rules) > 0:
            self.output_formatted_lines(rules, ofile)
            
        ofile.write("-----Res Balance Table------\n")
        balances = list()
        for node in network.nodes :
            #Evgenii 3-31-11 added if below in case Res does not have group id
            if not bool(gid):
                print "Error - Reservior needs Group ID"
                continue
            if node.type == ntype:
                gid = self.get_value(node, u"Rule Group ID", False)              
                if node.id in gid:
                    if self.get_value(node, u"Balance on Group (0) or Lead Reservior Volume(1)", False) == 0:
                        table_name = u"Balance Table (for balance on group)"
                        group_or_lead = 0  
                    else:
                        table_name = u"Balance Table (for balance on lead reservoir)"
                        group_or_lead = 1
                    
                    table = self.get_value(node, table_name, False)
                    
                    if numpy.alltrue(table == 0):
                        continue
                    formatters = self.get_table_formatter(node, table_name)                    
                    for row in table:
                        output = [u"Balance:", 1, 1, "%i" % node.id, "%i" % group_or_lead]
                        if group_or_lead == 1:
                            output.append("0")
                        for i, val in enumerate(row):
                            #FIX THIS!!!!!!!!!!!!!!
                            if val == "-1,#IND":
                                break
                            elif group_or_lead == 0:
                                if i != 0 and i % 2 == 0:
                                    output.append("0")
                            output.append(formatters[i] % val)
                        balances.append(output)
        if len(balances) > 0:
            self.output_formatted_lines(balances, ofile)             
    
    
    def get_table_formatter(self, obj, fieldname):
        """
        Returns a list of formatter for the given column of the table field of the object
        """
        field = self.get_objectfield(obj.type, fieldname)
        definition = field.attribute_type
        # FIXME : check if definition is a Table
        formats = list()
        for col in definition.columns:
            if col.format in ["integer", "binary"]:
                formats.append("%i")
            else:
                formats.append("%s")
        return formats
            
    def write_pump_hydropower(self, network, ofile, session):
        """
        Write the pump and hydropower information to the ofile
        """
        ofile.write("******Pumping and Hydropower********* \n")
        pumps = []        
        ltypes = self.session.query(nt.LinkType).filter( \
                or_(nt.LinkType.name == u"Diversion Link",
                    nt.LinkType.name == u"Unidirectional Link",
                    nt.LinkType.name == u"Groundwater Link",
                    nt.LinkType.name == u"Surface Bidirectional Link",
                    nt.LinkType.name == u"Demand Link",
                    nt.LinkType.name == u"Demand/Diversion Link")).all()        
        
        for link in network.links:
            if link.type not in ltypes:
                continue
            if self.get_value(link, u"Hydropower Enabled?", False) > 0:
                pumps.append( ("Power:",
                               1,
                               1,
                               1,
                               link.id,
                               self.get_value(link, u"Power Capacity"),
                               self.get_value(link, u"Operating Time Factor"),
                               0,
                               self.get_value(link, u"Turbine Elevation"),
                               0,
                               self.get_value(link, u"Power Efficiency"),
                               self.get_value(link, u"Min Flow"),
                               )
                              )
            if self.get_value(link, u"Pumping Enabled?", False) > 0:
                pumps.append( ("Pump:",
                               1,
                               1,
                               1,
                               link.id,
                               0,
                               0,
                               0,
                               0,
                               0,
                               self.get_value(link, u"Pump Efficiency"),
                               0
                               )
                              )            
        if len(pumps) > 0:
            self.output_formatted_lines(pumps, ofile)        
            
    def write_groundwater(self, network, ofile, session):
        """
        Exports the GW info to ofile
        """
        gwtype = self.session.query(nt.LinkType).filter( \
            nt.LinkType.name == u"Groundwater Link").first()
        surftype = self.session.query(nt.LinkType).filter( \
            nt.LinkType.name == u"Surface Bidirectional Link").first()
        # store nodes
        gwlinks = list()
        transfers = list()
        for link in network.links:
            if link.type is gwtype:
                comp_method = int(self.get_value(link,
                                    u"GW flow Computation Method", False) )
                fname_8 = u"Length" if comp_method in [2,4,5] else u"Link Area"
                gwlinks.append(("Groundwater:", 1, 1,
                                COMPONENTS[LINK_POLICY_COMP],
                                link.id,
                                int( comp_method - 1),
                                self.get_value(link, u"K"),
                                self.get_value(link, u"Link Elevation"),
                                self.get_value(link, fname_8),
                                self.get_value(link, u"Width"),
                                ))
                flow_matrix = self.get_value(link, u"GW Flow Matrix")
                if not isinstance(flow_matrix, numpy.ndarray):
                    continue
                for row in flow_matrix:
                    transfers.append(("Transfer:", 1, 1, link.id,
                                     row[0], row[1], row[2]))
            elif link.type is surftype:
                gwlinks.append(("Groundwater:", 1, 1,
                                COMPONENTS[LINK_POLICY_COMP],
                                link.id,
                                0,
                                0,
                                0,
                                0,
                                0
                                ))            
                flow_matrix = self.get_value(link, u"Flow Matrix")
                if not isinstance(flow_matrix, numpy.ndarray):
                    continue
                for row in flow_matrix:
                    transfers.append(("Transfer:", 1, 1, link.id,
                                     row[0], row[1], row[2]))                
        if len(gwlinks) > 0:
            ofile.write("***********GW Link DATA**************\n")
            self.output_formatted_lines(gwlinks, ofile)
        else:
            logging.info("No Groundwater link data in file.")
        if len(transfers) > 0:
            ofile.write("**********GW Transer***************\n")
            self.output_formatted_lines(transfers, ofile)
        else:
            logging.info("No Groundwater transfer in file.")
    
    def write_routing(self, network, ofile, session):
        """
        Write the routing rules for the surface links
        """
        ltypes = self.session.query(nt.LinkType).filter( \
                or_(nt.LinkType.name == u"Diversion/Demand Link",
                    nt.LinkType.name == u"Unidirectional Link",
                    nt.LinkType.name == u"Demand Link",
                    nt.LinkType.name == u"Diversion Link")).all()
        routings = []
        for link in network.links:
            if link.type in ltypes:
                routing_method = int(self.get_value(link, u"Routing Method"))
                if routing_method == 1:
                    routings.append(("Routing:", 1, 1,
                                     COMPONENTS[LINK_POLICY_COMP],
                                     link.id,
                                     routing_method,
                                     self.get_value(link, u"Linear Parameter"),
                                     self.get_value(link, u"Exponent"),
                                     self.get_value(link, u"Detention Storage"),
                                     0
                                     ))
                elif routing_method == 2:
                    routings.append(("Routing:", 1, 1,
                                     COMPONENTS[LINK_POLICY_COMP],
                                     link.id,
                                     routing_method,
                                     self.get_value(link, u"Number of Cascading Reservoirs"),
                                     self.get_value(link, u"a (inflow parameter)"),
                                     self.get_value(link, u"b (volume parameter)"),
                                     self.get_value(link, u"c (exponent)")
                                     ))                    
        if len(routings) > 0:
            ofile.write("*****ROUTING*****\n")
            self.output_formatted_lines(routings, ofile)
        
    def write_gage(self, network, ofile, flowfile, demfile, session):
        """
        Write the content of the gage file
        """
        FLOW_FIELD_NAME = u"Flow Input"
        DEM_FIELD_NAME = u"Demand Time Series"
        ofile.write(u"FLOWFILE\n")
        ofile.write(u"\nNatural Flow\n")
        
        gage_nodes = list()
        gage_node_flows = list()
        
        #demand time-series Evgenii added 040111
        dem_nodes = list()
        dem_node_series = list()

        for node in network.nodes:
            if self.has_value(node, FLOW_FIELD_NAME) == 1:
                gage_nodes.append(node)
                gage_node_flows.append(self.get_value(node, FLOW_FIELD_NAME))
  
       #demand time-series Evgenii added 040111
        for node in network.nodes:
            if self.has_value(node, DEM_FIELD_NAME) == 1:
                dem_nodes.append(node)
                dem_node_series.append(self.get_value(node, DEM_FIELD_NAME))

  
        if len(gage_nodes) is 0:
            logging.warn("No gage nodes in network")
            #return
        
        if len(dem_nodes) is 0:
            logging.warn("No demand time series in network")
            #return
        
        ofile.write("%s\n" % len(gage_nodes))
        for node in gage_nodes:
            has_flow_factor = 0
            if self.get_value(node, u"Flow Factors Available?", False) > 0:
                has_flow_factor = 1
            ofile.write("%s\t0.0864\t%s\n" % (node.name, has_flow_factor))
        #Write demand time-series Evgenii added 040111
        ofile.write(u"Demand Time Series\n")        
        ofile.write("%s\n" % len(dem_nodes))
        for node in dem_nodes:
            ofile.write("%s\n" % (node.name))
  
        #flowfile.write("FLOWDATA\n")

        if len(gage_nodes)>0:
            for i in xrange(len(gage_node_flows[0])):
                for flow in gage_node_flows:
                    if len(flow) >= i+1:
                        flowfile.write("%s " % flow[i,0])
                flowfile.write("\n")
        #flowfile.write("END OF DATA")
        
       
      #Write demand time-series Evgenii added 040111        
        if len(dem_nodes)>0:
            for i in xrange(len(dem_node_series[0])):
                for dem in dem_node_series:
                    if len(dem) >= i+1:
                        demfile.write("%s " % dem[i,0])
                demfile.write("\n")
    def write_def(self, network, ofile, session, sub_time_steps, days_per_period, user_node_seq, total_runs=1):
        """
        Write the iras.def file
        """
            
        ofile.write(
'''DEFINITION
!
''')
        ofile.write("%s %s %s %s %s %s \n" % (network.project.horizon_from.year, \
                                     network.project.horizon_to.year, \
                                     sub_time_steps,
                                     days_per_period,
                                     total_runs,
                                     user_node_seq))
        for year in xrange(network.project.horizon_from.year, network.project.horizon_to.year+1):
            ofile.write('%s %s\n' % (year, 1))
        
    def write_pol(self, network, ofile, session):
        """
        Write the policy file
        """
        ofile.write(\
"""IRAS: Network
!PolicyID, BegDate, EndDate
SysEvaporation: 1,1,365.999
!POLICIES FOR NODES AND LINKS
POLICIES
"""
        )
        #Evgenii - Instead of writing policy data through node.type, it should cycle through node and node fields, that way policies for fields that have no data will not export in the iras.pol file

        # Hossam - can get value for a field by using node.getFieldValue(session,fd)
        # fd must be an element from the array of node.type.fields
        for node in network.nodes:
            if self.policies.has_key(node.type):
                for pol in self.policies[node.type]:                    
                    if len(pol.valid_ids) > 0:
                        if node.id in pol.valid_ids:
                            #Evgenii - here export should be based on node fields not just on node for the reason stated above)
                          string = pol.export_str_policy(node,session)
                          if string:
                            ofile.write(string)
                    else:
                      string = pol.export_str_policy(node,session)
                      if string:
                        ofile.write(string)
        for link in network.links:
            if self.policies.has_key(link.type):
                for pol in self.policies[link.type]:
                    if len(pol.valid_ids) > 0:
                        if link.id in pol.valid_ids:
                            logging.debug('Accepted link for policy for %s' % link.id)
                            ofile.write(pol.export_str_policy(link) + "\n")
                        else:
                            logging.debug('Rejecting link for policy for %s' % link.id)
                    else:
                        logging.debug('No filter policy for %s' % link.id)
                    #    ofile.write(pol.export_str_policy(link) + "\n")
 
        ofile.write(
"""END OF POLICIES
!PolicyGrpID,PolicyType,PolicyID,CompType,CompID (iNodeLinkID),BegDate,EndDate
!CompType says if its a for a node (CompType=1) or link (2)
"""
        )
        
        
    def write_unt(self, network, ofile, session):
        """
        Write the unit file for IRAS.
        
        FIXME : hardcoded parameters . Content should be generated depending on the configuration
        """
        ofile.write("""          
Units:1 1 1
Units:1 2 10000
Units:1 3 1
Units:1 4 0.0864
Units:1 5 0.001
Units:1 6 1
Units:1 7 1
Units:2 1 1
Units:2 2 1
Units:2 3 1
Units:2 4 0.0864
Units:2 5 0.001
Units:2 6 1
Units:2 7 1
"""
            )
    def write_chg(self, network, ofile, session):
        #Write iras-chg file, Evgenii 061211
        ofile.write("NON-POLICY CHANGES\n")
        ofile.write("END OF NON-POLICY CHANGES\n")       
        
    def flows_to(self, link, typenames):
        """
        Returns true if link flows to the given nodetype
        """
        import types
        if typenames is types.StringTypes:
            typenames = [typenames]
        for name in typenames:
            ntype = self.session.query(nt.NodeType).filter( \
                nt.NodeType.name == name).first()
            if ntype is None:
                continue
            else:
                if link.end_node_id == ntype.id:
                    return 1
                else: continue
        else:
            return 0

        
    def get_objectfield(self, objecttype, fieldname):
        """
        Returns the Field object associated with the fieldname for the given
        objecttype
        """
        if isinstance(objecttype, nt.NodeType):
            search = nt.NodeField
            ftype = search.node_type_id
            key = u"n" + unicode(objecttype.id) + fieldname
        elif isinstance(objecttype, nt.LinkType):
            search = nt.LinkField
            ftype = search.link_type_id
            key = u"l" + unicode(objecttype.id) + fieldname
        else:
            raise Exception("Unknown type")
        
        if not self.fields.has_key(key):
            field = self.session.query(search).filter(\
                and_(search.name == fieldname, \
                     ftype == objecttype.id)).first()
            if field is not None:
                self.fields[key] = field
                return field
            else:
                return None
        else:
            return self.fields[key]
    
    def has_value(self, obj, fieldname):
        """
        Returns 0 if obj has no value, 1 if has value
        """
        field = self.get_objectfield(obj.type, fieldname)
        if field is None:
            return 0        
        fval = obj.getFieldValue(self.session, field)
        if fval is None:
            return 0
        elif fval.value is None:
            return 0
        else:
            if numpy.all(numpy.isnan(fval.value)):
                return 0
            else:
                return 1
        
    
    def get_depending_value(self, obj, fieldname, depfieldname, formatted=True):
        """
        Returns the value of the defieldname depending on the value of fieldname
        
        Example:
        
        if routing is 0 : return 0
        if routing is 1 : return Initial Storage 1 value
        if routing is 2 : return Initial Storage 2 value
        """
        
        value = int(self.get_value(obj, fieldname, False))
        if value is 0:
            return value
        else:
            logging.debug("Getting %s %s" % (depfieldname, value))
            return self.get_value(obj, u"%s %s" % (depfieldname, value), formatted)
        
    def get_value(self, obj, fieldname, formatted=True):
        """
        Returns the value of the field for the given fieldname and obj.
        If field value is None, returns 0
        """
        field = self.get_objectfield(obj.type, fieldname)
        
        if field is None:
            message = "No field named %s for object type %s" % \
                          (fieldname, obj.type.name)
            #logging.debug(message)
            return 0
        
        fval = obj.getFieldValue(self.session, field)
        if fval is None:
            return 0
        elif fval.value is None:
            return 0
        else:
            if formatted is False:
                return fval.value
            try:
                format = field.attribute_type.format            
            except AttributeError:
                # should mean there is no format attribute
                return fval.value

            if isinstance(fval.value, numpy.ndarray):
                return fval.value
            
            if format == "integer":
                if isinstance(fval.value, list):
                    try:
                        return "%i" % fval.value[0]
                    except IndexError:
                        return 0
                return "%i" % fval.value            
            elif format == "binary":
                return "%x" % fval.value
            elif format == "float":
                return "%f" % fval.value
            else:
                return fval.value
            
    

    def output_formatted_lines(self, vlist, ofile):
        """
        Write the list of list of values to the ofile
        """
        if vlist is None or len(vlist) == 0:
            logging.warn("Trying to export a empty list to file")
            return
        # get format values
        #f = open('output.txt', 'w')
        #puts 1's in a list with as many members as the first member in vlist
        formats = [1 for i in xrange(len(vlist[0]))]
        #f.write("formats is %s\n" % formats)
        #ofile.write(formats)
        #logging.warn("Formats is %s" %s formats)
        #en_values=enumerate(values)
        #ofile.write(en_values)
        #.warn("Values enuermated is %s" %s en_values)
        #f = open('output.txt', 'w')              
        for values in vlist:
            for i, val in enumerate(values):
                #f.write("Val is %s\n" % val)
                #f.write("I is %s\n" % i)
                if len(unicode(val)) > formats[i]:
                    #f.write("Now in the f statement\n")
                #f.write("%s\n" % val))
                    #f.write("Unicode val is %s\n" % str(unicode(val)))
                    #f.write("%s\n" % len(unicode(val))
                    #f.write("%s\n" % formats)
                    #f.write("%s\n" % val)
                    #f.write("%s\n" % i)
                    formats[i] = len(unicode(val))
                    
        # build the format string
        #f.close()
        string_format =""
        for f in formats:
            string_format += "%%-%ss " % f
        string_format += "\n"

        # write the node lines
        for values in vlist:
            ofile.write(string_format % tuple(values))        
            
            
 
# Because the IrasExport does need user input, it has been removed from
# the default exporter window
#REGISTRY = ExporterRegistry()
#REGISTRY.register(IrasExporter)
#logging.info("IRAS export extension registered")

